﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;

using MyBasicLib.Extensions;
using MyBasicLib.Reflection;
using MyBasicLib.Data.ORMLiteNew;
using RUC.Core.Entities;
namespace MyBasicLib.Test
{

    [TestClass]
    public class FastReflectionTest
    {

        [TestMethod]
        public void FastReflectionTestMethod1()
        {
            var tt = new FastReflectionTestHelper();
            var expected = "rfgtdd";
            var pi = tt.GetType().GetProperty("Pi1", BindingFlags.Instance | BindingFlags.Public);
            pi.FastSetValue(tt, expected);
            var actual = pi.FastGetValue(tt);
            Assert.AreEqual(expected, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod2()
        {
            var tt = new FastReflectionTestHelper();
            var expected = 6;
            var pi = tt.GetType().GetProperty("Pi2", BindingFlags.Instance | BindingFlags.Public);
            pi.FastSetValue(tt, expected);
            var actual = pi.FastGetValue(tt);
            Assert.AreEqual(expected, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod3()
        {
            var tt = new FastReflectionTestHelper();
            var expected = "xdgbhdxed";
            var mi = tt.GetType().GetMethod("Setfs1", BindingFlags.Static | BindingFlags.Public);
            mi.FastInvoke(tt, expected);
            var fi = tt.GetType().GetField("fs1", BindingFlags.Static | BindingFlags.NonPublic);
            var actual = fi.FastGetValue(tt);
            Assert.AreEqual(expected, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod4()
        {
            var tt = new FastReflectionTestHelper();
            var expected = 6;
            var mi = tt.GetType().GetMethod("Setfs2", BindingFlags.Static | BindingFlags.Public);
            mi.FastInvoke(tt, expected);
            var fi = tt.GetType().GetField("fs2", BindingFlags.Static | BindingFlags.NonPublic);
            var actual = fi.FastGetValue(tt);
            Assert.AreEqual(expected, actual);
        }


        [TestMethod]
        public void FastReflectionTestMethod6()
        {
            var tt = new FastReflectionTestHelper();
            var actual = tt.GetType().GetMethod("Test1", BindingFlags.Instance | BindingFlags.NonPublic).FastInvoke(tt, 5, 6);

            Assert.AreEqual(11, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod7()
        {
            var tt = new FastReflectionTestHelper();
            var actual = tt.GetType().GetMethod("Test2", BindingFlags.Static | BindingFlags.NonPublic).FastInvoke(null, 5, 6);

            Assert.AreEqual(11, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod8()
        {
            var tt = new FastReflectionTestHelper();
            var actual = tt.GetType().GetMethod("Test3", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt, 5, 6);

            Assert.AreEqual(11, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod9()
        {
            var tt = new FastReflectionTestHelper();
            var actual = tt.GetType().GetMethod("Test4", BindingFlags.Static | BindingFlags.Public).FastInvoke(null, 5, 6);

            Assert.AreEqual(11, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod10()
        {
            var dt = DateTime.Now;
            var actual = typeof(DateTime).GetMethod("AddDays").FastInvoke(dt, 1d);
            Assert.AreEqual(dt.AddDays(1), actual);

        }
        [TestMethod]
        public void FastReflectionTestMethod11()
        {
            var dt = new MyStruct(5);
            var actual = typeof(MyStruct).GetMethod("Add").FastInvoke(dt, 1d);
            var expect = dt.Add(1);
            Assert.AreEqual(expect, actual);

        }
        [TestMethod]
        public void FastReflectionTestMethod12()
        {
            var dt = new MyObject(5);
            var actual = typeof(MyObject).GetMethod("Add").FastInvoke(dt, 1d);
            var expect = dt.Add(1);
            Assert.AreEqual(expect.I, ((MyObject)actual).I);

        }
        [TestMethod]
        public void FastReflectionTestMethod13()
        {
            var tt = new FastReflectionTestHelper();
            var mo = new MyObject(3);
            // MyObject Test5(int a, MyObject b) 
            var actual = tt.GetType().GetMethod("Test5", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt, 5, mo);
            var expect = tt.Test5(5, mo);
            Assert.AreEqual(expect.I, ((MyObject)actual).I);

        }
        [TestMethod]
        public void FastReflectionTestMethod14()
        {
            var tt = new FastReflectionTestHelper();
            var mo = new MyStruct(3);
            // MyStruct Test5(int a, MyStruct b) 
            var actual = tt.GetType().GetMethod("Test7", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt, 5, mo);
            var expect = tt.Test7(5, mo);
            Assert.AreEqual(expect.I, ((MyStruct)actual).I);

        }
        [TestMethod]
        public void FastReflectionTestMethod15()
        {
            ITest tt = new FastReflectionTestHelper();
            var actual = tt.GetType().GetMethod("Test", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt, 5, 6);
            var expect = tt.Test(5, 6);
            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod18()
        {
            var tt = new FastReflectionTestHelper();
            var actual = tt.GetType().GetMethod("Test6", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt, 5, 6);

            Assert.AreEqual(11, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod19()
        {
            var tt = new[] { 1, 2, 3 };
            System.Linq.Expressions.Expression<Func<object, int>> func = p => tt[1];

            var actual = func.Body.Eval();
            Assert.AreEqual(2, actual);
        }
        //[TestMethod]
        //public void FastReflectionTestMethod20()
        //{
        //    var dt = new MyObject(5);
        //    var actual = typeof(MyObject).GetMethod("Add").FastInvoke(this, 1d);
        //    var expect = dt.Add(1);
        //    Assert.AreEqual(expect.I, ((MyObject)actual).I);

        //}

        [TestMethod]
        public void FastReflectionTestMethod25()
        {
            var tt = new NativeMethods();
            var actual = tt.GetType().GetMethod("GetCurrentThread", BindingFlags.Static | BindingFlags.NonPublic).FastInvoke(null);
            var expect = 0;

            Assert.AreNotEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod26()
        {
            var tt = new NativeMethods();
            Guid guid = Guid.Empty;
            var args = new object[] { guid };
            var actual = tt.GetType().GetMethod("UuidCreateSequential", BindingFlags.Static | BindingFlags.NonPublic).FastInvoke(null, args);
            guid = (Guid)args.FirstOrDefault();
            var expect = 0;

            Assert.AreEqual(expect, actual);
            Assert.AreNotEqual(Guid.Empty, guid);
        }
        [TestMethod]
        public void FastReflectionTestMethod30()
        {
            var tt = new FastReflectionTestHelperChild();
            var actual = typeof(FastReflectionTestHelper).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelperChild";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod301()
        {
            FastReflectionTestHelper tt = new FastReflectionTestHelperChild();
            var actual = typeof(FastReflectionTestHelper).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelperChild";

            Assert.AreEqual(expect, actual);
        }

        [TestMethod]
        public void FastReflectionTestMethod31()
        {
            var tt = new FastReflectionTestHelperChild();
            var actual = typeof(FastReflectionTestHelperChild).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelperChild";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod311()
        {
            FastReflectionTestHelper tt = new FastReflectionTestHelperChild();
            var actual = typeof(FastReflectionTestHelperChild).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelperChild";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod32()
        {
            var tt = new FastReflectionTestHelperChild2();
            var actual = typeof(FastReflectionTestHelper).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelper";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod321()
        {
            FastReflectionTestHelper tt = new FastReflectionTestHelperChild2();
            var actual = typeof(FastReflectionTestHelper).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelper";

            Assert.AreEqual(expect, actual);
        }


        [TestMethod]
        public void FastReflectionTestMethod33()
        {
            var tt = new FastReflectionTestHelperChild2();
            var actual = typeof(FastReflectionTestHelperChild2).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelperChild2";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod331()
        {
            FastReflectionTestHelper tt = new FastReflectionTestHelperChild2();
            var actual = typeof(FastReflectionTestHelperChild2).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelperChild2";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod34()
        {
            FastReflectionTestHelper tt = new FastReflectionTestHelperChild2();
            var actual = typeof(ITest).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public).FastInvoke(tt);

            var expect = "FastReflectionTestHelper";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod35()
        {
            var ds = new System.Collections.ObjectModel.ReadOnlyCollection<string>(new[] { "sdsdfsd" });

            System.Linq.Expressions.Expression<Func<string>> fun = () => ds.ElementAt(0);

            var actual = fun.Body.Eval();
            var expect = "sdsdfsd";

            Assert.AreEqual(expect, actual);
        }
        [TestMethod]
        public void FastReflectionTestMethod36()
        {
            var ds = new[] { "sdsdfsd" };

            System.Linq.Expressions.Expression<Func<string>> fun = () => ds.ElementAt(0);

            var actual = fun.Body.Eval();
            var expect = "sdsdfsd";

            Assert.AreEqual(expect, actual);
        }
    }
    public interface ITest
    {
        string Print();
        int Test(int a, int b);
    }
    public class FastReflectionTestHelper : ITest
    {
        public string Pi1 { get { return fi1; } set { fi1 = value; } }
        private string fi1;


        public int Pi2 { get { return fi2; } set { fi2 = value; } }
        private int fi2;
        private static string fs1;
        private static int fs2;

        public static void Setfs1(string a)
        {
            fs1 = a;
        }
        public static void Setfs2(int a)
        {
            fs2 = a;
        }

        public int Test(int a, int b)
        {
            return a + b;

        }
        int Test1(int a, int b)
        {
            return a + b;
        }

        static int Test2(int a, int b)
        {
            return a + b;
        }

        public int Test3(int a, int b)
        {
            return a + b;
        }
        public static int Test4(int a, int b)
        {
            return a + b;
        }
        public MyObject Test5(int a, MyObject b)
        {
            return b.Add(a);
        }
     
        public int Test6(int a, int b)
        {
            return Test3(a,b);
        }

        public MyStruct Test7(int a, MyStruct b)
        {
            return b.Add(a);
        }

        public virtual string Print()
        {
            return "FastReflectionTestHelper";
        }
    }
    public class FastReflectionTestHelperChild : FastReflectionTestHelper
    {
        public override string Print()
        {
            return "FastReflectionTestHelperChild";
        }
    }
    public class FastReflectionTestHelperChild2 : FastReflectionTestHelper
    {
        public new string Print()
        {
            return "FastReflectionTestHelperChild2";
        }
    }
    public struct MyStruct
    {
        public double I;
        public MyStruct(double i) { I = i; }
        public MyStruct Add(double i)
        {
            return new MyStruct(I + i);
        }
    }

    public class MyObject
    {
        public double I;
        public MyObject(double i) { I = i; }
        public MyObject Add(double i)
        {
            return new MyObject(I + i);
        }
    }
}
